package com.changgou.order.service.impl;

import com.alibaba.fastjson.JSON;
import com.changgou.entity.Result;
import com.changgou.feign.SkuFeign;
import com.changgou.order.dao.PreferentialMapper;
import com.changgou.order.service.CartService;
import com.changgou.pojo.OrderItem;
import com.changgou.pojo.Preferential;
import com.changgou.pojo.Sku;
import com.sun.org.apache.xerces.internal.xs.datatypes.ObjectList;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @Project: com.changgou.order.service.impl
 * @Author: ShaoDi Wang
 * @Date: Created in 2019-08-06 19:58
 * @Description:
 * @Version: 1.0
 */
@Service
public class CartServiceImpl implements CartService {

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private SkuFeign skuFeign;

    @Autowired
    private PreferentialMapper preferentialMapper;

    private final String prefKey="preferential";

    /**
     * 购物车
     */
    private final String cartKey="cartList";

    /**
     * 收藏夹
     */
    private final String collectKey="collectList";

    /**
     * 查询某个购物车中的某条数据
     *
     * @param username 用户名
     * @return
     */
    @Override
    public Map findCart(String username) {
        //从redis中提取购物车列表
        List<Map<String,Object>> cartList = (List<Map<String,Object>>)
        redisTemplate.boundHashOps(cartKey).get(username);
        if(cartList==null){
            cartList =new ArrayList();
        }
        //返回值
        Map result =new HashMap(5);
        result.put(cartKey,cartList);

        //合计数量和金额计算
        //获取选中的购物车
        List<OrderItem> orderItemList = cartList.stream()
                .filter( cart -> (boolean) cart.get( "checked" ) )
                .map( cart -> (OrderItem) cart.get( "item" ) )
                .collect( Collectors.toList() );
        //数量合计
        int num = orderItemList.stream().mapToInt(OrderItem::getNum).sum();
        int money = orderItemList.stream().mapToInt( OrderItem::getMoney ).sum();
        result.put( "num",num );
        result.put( "money",money );

        //优惠金额计算
        //购物车分组
        Map<Integer, Integer> orderItemsGroup = orderItemList.stream()
                .collect( Collectors.groupingBy( OrderItem::getCategoryId3, Collectors.summingInt( OrderItem::getMoney ) ) );
        System.out.println("分组后的购物车"+orderItemsGroup);

        //优惠金额
        int preMoney=0;
        for(Integer categoryId:  orderItemsGroup.keySet() ){
            preMoney+= getPreMoney( categoryId, orderItemsGroup.get( categoryId ) );
        }
        result.put( "preMoney",preMoney );
        result.put( "payMoney", money-preMoney);

        return result;
    }

    /**
     * 添加商品到购物车
     *
     * @param username
     * @param skuId
     * @param num
     */
    @Override
    public void add(String username, String skuId, Integer num) {
        //查询购物车
        List<Map<String,Object>> cartList = ( List<Map<String,Object>>)redisTemplate.boundHashOps( cartKey).get( username );
        if(cartList==null){
            cartList=new ArrayList<>(  );
        }
        //购物车是否存在该商品
        boolean flag=false;
        //判断当前购物车列表中是否存在该商品
        for( int i=0;i<cartList.size();i++){
            Map cart=cartList.get( i );
            OrderItem orderItem= (OrderItem)cart.get( "item" );
            //如果存在
            if(orderItem.getSkuId().equals( skuId )){
                if(orderItem.getNum()==null){
                    orderItem.setNum( 0 );
                }
                //数量
                orderItem.setNum( orderItem.getNum()+ num   );
                //金额
                orderItem.setMoney( orderItem.getNum()*orderItem.getPrice() );
                //重量
                orderItem.setAllWeight( orderItem.getWeight()* orderItem.getNum() );
                //判断数量是否为0或负数
                if(orderItem.getNum()<=0){
                    cartList.remove( cart );
                }
                flag=true;
                break;
            }
        }

        //如果不存在，添加此商品到购物车
        if(!flag){

            Result skuResult = skuFeign.findById( skuId );
            if(!skuResult.isFlag()){
                throw new RuntimeException( "远程调用出错" );
            }
            if(skuResult.getData()==null){
                throw new RuntimeException( "商品不存在" );
            }
            Sku sku= JSON.parseObject(JSON.toJSONString(skuResult.getData()) , Sku.class  )  ;
            if( !"1".equals(sku.getStatus()  ) ){
                throw new RuntimeException( "商品状态不合法" );
            }
            if( !"1".equals(sku.getIsMarketable() ) ){
                throw new RuntimeException( "商品未上架" );
            }
            if( "1".equals(sku.getIsDelete() ) ){
                throw new RuntimeException( "商品已删除" );
            }

            OrderItem orderItem=new OrderItem();
            orderItem.setSkuId( skuId );
            orderItem.setSpuId( sku.getSpuId()  );
            orderItem.setNum( num );
            orderItem.setPrice( sku.getPrice() );
            orderItem.setMoney( sku.getPrice()* num );
            orderItem.setImage( sku.getImage() );
            orderItem.setWeight( sku.getWeight());
            orderItem.setAllWeight( sku.getWeight()*num );
            orderItem.setCategoryId1( sku.getCategory1Id() );
            orderItem.setCategoryId2( sku.getCategory2Id() );
            orderItem.setCategoryId3( sku.getCategory3Id() );
            orderItem.setName( sku.getName() );
            orderItem.setIsReturn( "0" );

            Map map=new HashMap(2);
            map.put( "item",orderItem );
            map.put( "checked",true );
            cartList.add( map );

        }
        //保存购物车到redis
        redisTemplate.boundHashOps( cartKey).put( username,cartList );
    }

    /**
     * 更新选中状态
     *
     * @param username
     * @param skuId
     * @param checked
     */
    @Override
    public boolean updateChecked(String username, String skuId, boolean checked) {
        //查询购物车
        List<Map<String,Object>> cartList = ( List<Map<String,Object>>)redisTemplate.boundHashOps( cartKey).get( username );
        if(cartList==null){
            return false;
        }
        boolean flag=false;
        for(Map cart:cartList ){
            OrderItem orderItem = (OrderItem)cart.get( "item" );
            if(orderItem.getSkuId().equals( skuId )){
                cart.put( "checked",checked );
                flag=true;
            }
        }
        if(flag){
            redisTemplate.boundHashOps( cartKey).put( username,cartList );
        }
        return flag;
    }

    /**
     * 删除选中购物车
     *
     * @param username
     */
    @Override
    public void deleteChecked(String username) {
        //筛选未选中购物车
        List<Map<String,Object>> cartList = ( List<Map<String,Object>>)redisTemplate.boundHashOps( cartKey).get( username );
        if(cartList==null){
            cartList=new ArrayList<>(  );
        }
        List<Map<String, Object>> noCheckedCartList = cartList.stream()
                .filter( cart -> !(boolean) cart.get( "checked" ) )
                .collect( Collectors.toList() );
        //保存到redis
        redisTemplate.boundHashOps( cartKey).put( username, noCheckedCartList);
    }

    /**
     * 刷新购物车列表
     *
     * @param username 用户名
     * @return
     */
    @Override
    public List<Map<String, Object>> refreshCartList(String username) {

        //从redis中提取购物车
        List<Map<String, Object>> cartList =
                (List<Map<String, Object>>)redisTemplate.boundHashOps( cartKey ).get( username );
        if(cartList==null){
            return new ArrayList<>(  );
        }
        //循环购物车，获取最新价格
        for(int i=0;i<cartList.size();i++){
            Map cart = (Map)cartList.get( i );
            OrderItem orderItem= (OrderItem)cart.get( "item" );
            String skuId = orderItem.getSkuId();
            Result skuResult = skuFeign.findById( skuId );
            Map sku=(Map)skuResult.getData();
            if(sku!=null){
                //正常
                if("1".equals( (String)sku.get( "status" ) ) ){
                    //刷新价格
                    orderItem.setPrice( (Integer) sku.get( "price" ) );
                    //刷新金额
                    orderItem.setMoney( orderItem.getPrice()*orderItem.getNum() );
                }else{
                    //取消选中
                    cart.put( "checked",false );
                }
            }else{
                //从购物车中移除
                cartList.remove( cart );
            }
        }
        //存回redis
        redisTemplate.boundHashOps( cartKey ).put( username,cartList );
        return cartList;
    }

    /**
     * 将选中的购物车放到收藏夹
     *
     * @param username
     */
    @Override
    public void collectChecked(String username) {
        //获取选中的购物车
        List<Map<String,Object>> cartList = ( List<Map<String,Object>>)redisTemplate.boundHashOps( cartKey).get( username );
        if(cartList==null){
            cartList=new ArrayList<>(  );
        }
        List<OrderItem> orderItemList = cartList.stream()
                .filter( cart -> (boolean) cart.get( "checked" ) )
                .map( cart -> (OrderItem) cart.get( "item" ) )
                .collect( Collectors.toList() );

        //查询收藏夹原来的列表
        List<OrderItem> collectList= (List<OrderItem>)redisTemplate.boundHashOps( collectKey ).get( username );
        if(collectList==null){
            collectList=new ArrayList<>( );
        }
        //追加收藏夹内容
        collectList.addAll( orderItemList );

        //存回redis
        redisTemplate.boundHashOps( collectKey ).put( username, collectList);

        //删除选中购物车
        deleteChecked( username );

    }

    /**
     * 优惠金额计算
     * @param categoryId
     * @param money
     * @return
     */
    private int getPreMoney(Integer categoryId,int money){
        //优惠规则表查询
        List<Preferential> preferentialList = findPreferentialList( categoryId, money );
        //不翻倍优惠金额
        int preMoney1 = getPreMoney1( preferentialList );
        //翻倍优惠金额
        int preMoney2 = getPreMoney2( preferentialList, money );
        return preMoney1>preMoney2?preMoney1:preMoney2;
    }

    /**
     * 计算不翻倍优惠金额
     * @param preferentialList
     * @return
     */
    private int getPreMoney1( List<Preferential> preferentialList ){
        List<Preferential> preferentials = preferentialList.stream()
                .filter( preferential -> "1".equals( preferential.getType() ) )
                .sorted( Comparator.comparing( Preferential::getBuyMoney ).reversed() )
                .limit( 1 )
                .collect( Collectors.toList() );
        //如果存在优惠规则数据
        if(preferentials.size()>0){
            return preferentials.get( 0 ).getPreMoney();
        }else{
            return 0;
        }
    }

    /**
     * 计算翻倍优惠金额
     * @param preferentialList
     * @return
     */
    private int getPreMoney2( List<Preferential> preferentialList ,int money){
        List<Preferential> preferentials = preferentialList.stream()
                .filter( preferential -> "2".equals( preferential.getType() ) )
                .sorted( Comparator.comparing( Preferential::getBuyMoney ).reversed() )
                .limit( 1 )
                .collect( Collectors.toList() );
        //如果存在优惠规则数据
        if(preferentials.size()>0){
            //倍数
            int multiple = money/preferentials.get( 0 ).getBuyMoney();
            return preferentials.get( 0 ).getPreMoney()*multiple;
        }else{
            return 0;
        }
    }

    /**
     * 根据分类id和金额查询规则表
     * @param categoryId
     * @param money
     * @return
     */
    private List<Preferential> findPreferentialList(Integer categoryId,int money){
        //查询全部的优惠规则
        List<Preferential> preferentialList = (List<Preferential>)redisTemplate.boundValueOps( prefKey).get();
        if(preferentialList==null){
            preferentialList = preferentialMapper.selectAll();
            redisTemplate.boundValueOps( prefKey ).set(preferentialList  );
        }

        return  preferentialList.stream()
                .filter( preferential -> "1".equals( preferential.getState() ) )
                .filter( preferential -> preferential.getCategoryId().equals( categoryId ) )
                .filter( preferential -> preferential.getBuyMoney().intValue() <= money )
                .filter( preferential -> preferential.getStartTime().before( new Date() ) )
                .filter( preferential -> preferential.getEndTime().after( new Date() ) )
                .collect( Collectors.toList() );
    }
}
